import axios, { AxiosPromise, AxiosRequestConfig } from 'axios'
import { Toast as msg } from 'vant'
import configInfo from '@http/config'

const failTime = 1500 // 毫秒

const service = axios.create({
  baseURL: configInfo.baseUrl,
  withCredentials: false, // send cookies when cross-domain requests
  timeout: 1000 * 12 // 请求超时
})

// 设置post请求头
service.defaults.headers.post['Content-Type'] = 'application/json'

// 请求拦截器
service.interceptors.request.use(
  (config) => {
    // 每次发送请求之前判断是否存在token
    // 如果存在，则统一在http请求的header都加上token，这样后台根据token判断你的登录情况
    // 即使本地存在token，也有可能token是过期的，所以在响应拦截器中要对返回状态进行判断
    config.headers.Authorization = localStorage.getItem('AccessToken') || 'no-auth'
    // 有些接口是 config.headers.token = token
    return config
  },
  (error) => {
    // do something with request error
    console.log('请求拦截器出错：', error) // for debug
    return Promise.reject(error)
  }
)

// 响应拦截器
service.interceptors.response.use(
  (response) => {
    // 如果返回的状态码为200，说明接口请求成功，可以正常拿到数据
    // 否则的话抛出错误
    msg.fail({ message: '请求错误', duration: failTime })

    if (response.status === 200) {
      return Promise.resolve(response)
    }
    return Promise.reject(response)
  },
  // 服务器状态码不是2开头的的情况
  // 这里可以跟你们的后台开发人员协商好统一的错误状态码
  // 然后根据返回的状态码进行一些操作，例如登录过期提示，错误提示等等
  // 下面列举几个常见的操作，其他需求可自行扩展
  // eslint-disable-next-line consistent-return
  (error) => {
    msg.clear()

    if (error.response.status) {
      switch (error.response.status) {
        // 401: 未登录
        // 未登录则跳转登录页面，并携带当前页面的路径
        // 在登录成功后返回当前页面，这一步需要在登录页操作。
        case 401:
          msg.fail({
            message: '页面错误，请登录',
            duration: failTime
          })
          window.location.href = `/login?from=${window.location.href}`
          localStorage.clear()
          break

        // 403 token过期
        // 登录过期对用户进行提示
        // 清除本地token和清空vuex中token对象
        // 跳转登录页面
        case 403:
          msg.fail({
            message: '登录过期，请重新登录',
            duration: failTime
          })
          window.location.href = `/login?from=${window.location.href}`
          localStorage.clear()
          break

        // 404请求不存在
        case 404:
          msg.fail({
            message: '网络请求不存在',
            duration: failTime
          })
          break
        // 其他错误，直接抛出错误提示
        default:
          msg.fail({
            message: '网络请求错误',
            duration: failTime
          })
      }
      return Promise.reject(error.response)
    }
    // 处理断网的情况
    // eg:请求超时或断网时，更新state的network状态
    // network状态在app.vue中控制着一个全局的断网提示组件的显示隐藏
    // 关于断网组件中的刷新重新获取数据，会在断网组件中说明
    // store.commit('changeNetwork', false);
  }
)

// 最后导出实例
export default <responseDataClass>(config: AxiosRequestConfig) => {
  const timer = setTimeout(() => {
    msg.loading({ message: '加载中...', duration: 0 })
  }, 2500)
  return (service(config) as AxiosPromise<responseDataClass>).finally(() => {
    clearTimeout(timer)
  })
}
